package com.game.modular.game.battle.info.base;

import com.game.modular.game.match.service.PvpMatchEndServiceImpl;
import com.game.modular.game.playerMatch.domain.PvpCity;
import com.game.modular.game.match.service.PvpMatchServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

/**
 * pvp玩家信息
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PvpPlayerInfoServiceImpl extends PvpPlayerInfoBaseServiceImpl {
    @Resource
    private PvpMatchServiceImpl pvpMatchService;
    @Resource
    private PvpMatchEndServiceImpl pvpMatchEndServiceImpl;


    /**
     * 重新计算城池生产力
     */
    public void reduceCityProductivity(PvpCity pvpCity) {
        PvpPlayerInfo pvpPlayerInfo = get(pvpCity.getMatchId(), pvpCity.getOwnerUid());

        if (pvpPlayerInfo != null) {
            pvpPlayerInfo.setGrainRateCombined(pvpPlayerInfo.getGrainRateCombined() + pvpCity.getGrainRate());
            pvpPlayerInfo.setCopperRateCombined(pvpPlayerInfo.getCopperRateCombined() + pvpCity.getCopperRate());

            Set<Long> coreCityIds = pvpPlayerInfo.getCurrentCity();
            coreCityIds.add(pvpCity.getCoreCityId());
            pvpPlayerInfo.setCurrentCity(coreCityIds);// 更新

            Integer maxCity = pvpPlayerInfo.getMaxCity();
            if (coreCityIds.size() > maxCity) {
                maxCity = coreCityIds.size();
            }
            pvpPlayerInfo.setMaxCity(maxCity);// 更新
            savaCache(pvpPlayerInfo);
        }
    }

    /**
     * 占领城池后重新统计 城池消息,以及存活时间
     */
    public void reCountCityInfoAfterOccupy(
            @NotNull(message = "原主人不能为空") Long originalOwnerId,
            PvpCity pvpCity
    ) {
        Long matchId = pvpCity.getMatchId();
        Long ownerUid = pvpCity.getOwnerUid();
        Long coreId = pvpCity.getCoreCityId();
        if (originalOwnerId != null && originalOwnerId > 100) {
            PvpPlayerInfo original = get(matchId, originalOwnerId);
            original.removeAndFlushCityInfo(ownerUid, coreId);
            savaCache(original);
        }
        PvpPlayerInfo newOwner = get(matchId, ownerUid);
        newOwner.obtainAndFlushCityInfo(coreId);
        savaCache(newOwner);
        pvpMatchEndServiceImpl.tryMilitaryConquestSettlement(matchId);
    }

    /**
     * 获取存活玩家列表
     */
    public List<PvpPlayerInfo> obtainSurvivalList(Long currentMatchId) {
        return listCache(currentMatchId).stream() // 存活玩家
                .filter(pvpPlayerInfo -> !pvpPlayerInfo.getCurrentCity().isEmpty())
                .collect(Collectors.toList());
    }

    /**
     * 获取死亡玩家列表
     */
    public List<PvpPlayerInfo> obtainDeathlList(Long currentMatchId) {
        return listCache(currentMatchId).stream() // 存活玩家
                .filter(pvpPlayerInfo -> pvpPlayerInfo.getCurrentCity().isEmpty())
                .collect(Collectors.toList());
    }


    /**
     * 获取胜利玩家列表
     *
     */
    public List<PvpPlayerInfo> obtainWinnerlList(Long matchId) {
        List<PvpPlayerInfo> pvpPlayerInfos = obtainSurvivalList(matchId);
        Map<Set<Long>, List<PvpPlayerInfo>> collect =
                pvpPlayerInfos.stream()
                        .filter(item -> item.getIsExit()==0&&item.getIsDead()==0)
                        .collect(Collectors.groupingBy(PvpPlayerInfo::getAlliesUidList));
        if (collect.size() != 1) {
            return new ArrayList<>();
        }
        return collect.values().stream().flatMap(List::stream).collect(Collectors.toList());
    }

    /**
     * 统计击杀 击杀玩家数量|当前拥有的城池数量 排名
     */
    public void statisticalRanking(Long matchId) {
        List<PvpPlayerInfo> pvpPlayerInfos = listCache(matchId).stream()
                .peek(PvpPlayerInfo::setSurvivalTime)
                .collect(Collectors.toList());

        // 击杀玩家排名
        Map<Integer, List<PvpPlayerInfo>> collect = pvpPlayerInfos.stream()
                .collect(Collectors.groupingBy(item -> item.getKilledPlayers().size()));
        List<Map.Entry<Integer, List<PvpPlayerInfo>>> sortedEntries = collect.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByKey(Comparator.reverseOrder()))
                .collect(Collectors.toList());
        List<PvpPlayerInfo> killedPlayersRankList = new ArrayList<>();
        for (int i = 0; i < sortedEntries.size(); i++) {
            Map.Entry<Integer, List<PvpPlayerInfo>> entry = sortedEntries.get(i);
            List<PvpPlayerInfo> value = entry.getValue();
            for (PvpPlayerInfo pvpPlayerInfo : value) {
                pvpPlayerInfo.setKilledPlayersRank(i+1);
                killedPlayersRankList.add(pvpPlayerInfo);
            }
        }

        // 历史拥有城池数量排名
        Map<Integer, List<PvpPlayerInfo>> collect0 = killedPlayersRankList.stream()
                .collect(Collectors.groupingBy(PvpPlayerInfo::getMaxCity));
        List<Map.Entry<Integer, List<PvpPlayerInfo>>> sortedEntries0 = collect0.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByKey(Comparator.reverseOrder()))
                .collect(Collectors.toList());
        List<PvpPlayerInfo> maxCityRankList = new ArrayList<>();
        for (int i = 0; i < sortedEntries0.size(); i++) {
            Map.Entry<Integer, List<PvpPlayerInfo>> entry = sortedEntries0.get(i);
            List<PvpPlayerInfo> value = entry.getValue();
            for (PvpPlayerInfo pvpPlayerInfo : value) {
                pvpPlayerInfo.setMaxCityRank(i+1);
                maxCityRankList.add(pvpPlayerInfo);
            }
        }

        // 当前拥有城池数量排名
        Map<Integer, List<PvpPlayerInfo>> collect1 = maxCityRankList.stream()
                .collect(Collectors.groupingBy(item -> item.getCurrentCity().size()));
        List<Map.Entry<Integer, List<PvpPlayerInfo>>> sortedEntries1 = collect1.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByKey(Comparator.reverseOrder()))
                .collect(Collectors.toList());
        List<PvpPlayerInfo> currentCityRankList = new ArrayList<>();
        for (int i = 0; i < sortedEntries1.size(); i++) {
            Map.Entry<Integer, List<PvpPlayerInfo>> entry = sortedEntries1.get(i);
            List<PvpPlayerInfo> value = entry.getValue();
            for (PvpPlayerInfo pvpPlayerInfo : value) {
                pvpPlayerInfo.setCurrentCityRank(i+1);
                currentCityRankList.add(pvpPlayerInfo);
            }
        }

        // 更新统计
        for (PvpPlayerInfo pvpPlayerInfo : currentCityRankList) {
            update(pvpPlayerInfo);
        }

        // 更新排名
        for (PvpPlayerInfo pvpPlayerInfo : currentCityRankList) {
            pvpPlayerInfo.setRanking(pvpPlayerInfo.getCurrentCityRank());
            pvpPlayerInfo.setIsRuler(0);
            update(pvpPlayerInfo);
        }

        List<PvpPlayerInfo> winnerList = obtainWinnerlList(matchId);
        boolean end = !winnerList.isEmpty();
        if (end){// 征服胜利
            if (winnerList.size()==1){//单人征服
                PvpPlayerInfo pvpPlayerInfo = winnerList.get(0);
                pvpPlayerInfo.setRanking(1);
                pvpPlayerInfo.setIsRuler(1);
                update(pvpPlayerInfo);
            }if (winnerList.size()==2){// 2人征服
                // 如果有同盟一起统一天下的，则城池多的排第一名，城池少的第二名。
                PvpPlayerInfo pvpPlayerInfo1 = winnerList.get(0);
                PvpPlayerInfo pvpPlayerInfo2 = winnerList.get(1);
                int size1 = pvpPlayerInfo1.getCurrentCity().size();
                int size2 = pvpPlayerInfo2.getCurrentCity().size();
                if (size1>size2){
                    pvpPlayerInfo1.setRanking(1);
                    pvpPlayerInfo2.setRanking(2);
                }else if (size1<size2){
                    pvpPlayerInfo1.setRanking(2);
                    pvpPlayerInfo2.setRanking(1);
                }else {
                    //// 如果城池数量一样，则计算击杀数，如果击杀数多则排第一
                    long integral1 = pvpPlayerInfo1.getKilledPlayersRank();
                    long integral2 = pvpPlayerInfo2.getKilledPlayersRank();
                    if (integral1>integral2){
                        pvpPlayerInfo1.setRanking(1);
                        pvpPlayerInfo2.setRanking(2);
                    }else if (integral1<integral2){
                        pvpPlayerInfo1.setRanking(2);
                        pvpPlayerInfo2.setRanking(1);
                    }else {
                        pvpPlayerInfo1.setRanking(1);
                        pvpPlayerInfo2.setRanking(1);
                    }
                }
                pvpPlayerInfo1.setIsRuler(1);
                update(pvpPlayerInfo1);
                pvpPlayerInfo2.setIsRuler(1);
                update(pvpPlayerInfo2);
            }
        }

    }
}

